/**
 * $RCSfile$
 * $Revision: $
 * $Date: $
 *
 * Copyright 2003-2006 Jive Software.
 *
 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jivesoftware.smackx.packet;

import org.jivesoftware.smack.packet.PacketExtension;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Packet extension that contains the list of addresses that a packet should be
 * sent or was sent.
 * 
 * @author Gaston Dombiak
 */
public class MultipleAddresses implements PacketExtension {

	public static final String BCC = "bcc";
	public static final String CC = "cc";
	public static final String NO_REPLY = "noreply";
	public static final String REPLY_ROOM = "replyroom";
	public static final String REPLY_TO = "replyto";
	public static final String TO = "to";

	private List addresses = new ArrayList();

	/**
	 * Adds a new address to which the packet is going to be sent or was sent.
	 * 
	 * @param type
	 *            on of the static type (BCC, CC, NO_REPLY, REPLY_ROOM, etc.)
	 * @param jid
	 *            the JID address of the recipient.
	 * @param node
	 *            used to specify a sub-addressable unit at a particular JID,
	 *            corresponding to a Service Discovery node.
	 * @param desc
	 *            used to specify human-readable information for this address.
	 * @param delivered
	 *            true when the packet was already delivered to this address.
	 * @param uri
	 *            used to specify an external system address, such as a sip:,
	 *            sips:, or im: URI.
	 */
	public void addAddress(String type, String jid, String node, String desc,
			boolean delivered, String uri) {
		// Create a new address with the specificed configuration
		Address address = new Address(type);
		address.setJid(jid);
		address.setNode(node);
		address.setDescription(desc);
		address.setDelivered(delivered);
		address.setUri(uri);
		// Add the new address to the list of multiple recipients
		addresses.add(address);
	}

	/**
	 * Indicate that the packet being sent should not be replied.
	 */
	public void setNoReply() {
		// Create a new address with the specificed configuration
		Address address = new Address(NO_REPLY);
		// Add the new address to the list of multiple recipients
		addresses.add(address);
	}

	/**
	 * Returns the list of addresses that matches the specified type. Examples
	 * of address type are: TO, CC, BCC, etc..
	 * 
	 * @param type
	 *            Examples of address type are: TO, CC, BCC, etc.
	 * @return the list of addresses that matches the specified type.
	 */
	public List getAddressesOfType(String type) {
		List answer = new ArrayList(addresses.size());
		for (Iterator it = addresses.iterator(); it.hasNext();) {
			Address address = (Address) it.next();
			if (address.getType().equals(type)) {
				answer.add(address);
			}
		}

		return answer;
	}

	public String getElementName() {
		return "addresses";
	}

	public String getNamespace() {
		return "http://jabber.org/protocol/address";
	}

	public String toXML() {
		StringBuilder buf = new StringBuilder();
		buf.append("<").append(getElementName());
		buf.append(" xmlns=\"").append(getNamespace()).append("\">");
		// Loop through all the addresses and append them to the string buffer
		for (Iterator i = addresses.iterator(); i.hasNext();) {
			Address address = (Address) i.next();
			buf.append(address.toXML());
		}
		buf.append("</").append(getElementName()).append(">");
		return buf.toString();
	}

	public static class Address {

		private String type;
		private String jid;
		private String node;
		private String description;
		private boolean delivered;
		private String uri;

		private Address(String type) {
			this.type = type;
		}

		public String getType() {
			return type;
		}

		public String getJid() {
			return jid;
		}

		private void setJid(String jid) {
			this.jid = jid;
		}

		public String getNode() {
			return node;
		}

		private void setNode(String node) {
			this.node = node;
		}

		public String getDescription() {
			return description;
		}

		private void setDescription(String description) {
			this.description = description;
		}

		public boolean isDelivered() {
			return delivered;
		}

		private void setDelivered(boolean delivered) {
			this.delivered = delivered;
		}

		public String getUri() {
			return uri;
		}

		private void setUri(String uri) {
			this.uri = uri;
		}

		private String toXML() {
			StringBuilder buf = new StringBuilder();
			buf.append("<address type=\"");
			// Append the address type (e.g. TO/CC/BCC)
			buf.append(type).append("\"");
			if (jid != null) {
				buf.append(" jid=\"");
				buf.append(jid).append("\"");
			}
			if (node != null) {
				buf.append(" node=\"");
				buf.append(node).append("\"");
			}
			if (description != null && description.trim().length() > 0) {
				buf.append(" desc=\"");
				buf.append(description).append("\"");
			}
			if (delivered) {
				buf.append(" delivered=\"true\"");
			}
			if (uri != null) {
				buf.append(" uri=\"");
				buf.append(uri).append("\"");
			}
			buf.append("/>");
			return buf.toString();
		}
	}
}
